第五天要學習的目標是熟悉 flex 的應用,以及認識 CSS 選擇器、偽類別、切換 class 用的 toggle
要做到切完版後,點擊不同的區塊會有放大及上下文字滑入的動畫
Github 檔案位置:05 - Flex Panel Gallery
網頁一開始的樣子如下
可以先去看看 最後的成品 如下
將程式的要求拆分步驟後,我們需要做的事情如下
在開始使用 Flex 前建議大家先破關 FLEXBOX FROGGY,裡面有 24 個 Flex 小遊戲
首先我們先幫主體的 .panels{} 加上 display: flex 讓顯示轉為橫向

幫 .panel{} 加上 flex: 1 利用 flex 的屬性自動等分填滿主體範圍

在 .panel{}上利用 flex 屬性的 flex-direction 及 justify-content: center;,讓文字置中對齊(使用前要先display: flex)
.panel{
    display: flex;
    flex-direction: column;
    justify-content: center;
}

最後,以 * 通用選擇器 為 .panel 中的所有元素加上以下屬性,一樣是等分填滿和垂直平行置中對齊
.panel > * {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

這裡利用偽類別中的 :first-child 和 :last-child 單獨把上下兩段文字藏起來,以及寫好等等要做文字滑動特效的 class(此處選取的方式是 > 子代選擇器 和 .class 類別選擇器),
.panel > *:first-child{ transform: translateY(-100%); }
.panel.open-active > *:first-child{transform: translateY(0);} 
.panel > *:last-child{ transform: translateY(100%); }
.panel.open-active > *:last-child{transform: translateY(0);}
並利用 flex 靈活排版的特性,做簡單的 item CSS 放大動畫 class
.panel.open {
  flex: 5;
  font-size: 40px;
}
先利用前幾天學到的東西寫好 .panel 的 click 事件監聽
const panels = document.querySelectorAll('.panel');
    
function toggleOpen(){
  console.log(this);
}
panels.forEach(panel => {
  panel.addEventListener('click', toggleOpen);
});
這次比較不一樣的是,我們沒有使用 classList.add 和 classList.remove 兩個函式做 class 的添加和移除
而是用了 classList.toggle() 函式,他可以判斷 class 的有無而做開關,不需要拆分為 add 和 remove
function toggleOpen(){
  console.log(this);
  this.classList.toggle('open');
  this.classList.toggle('open-active');
}

如果我們想要等 item 完整的放大完再讓兩行文字飄進來的話,可以再利用之前學到的 transitionend 事件
要特別注意的是 flex 屬性在 TransitionEvent 中的 propertyName,部分瀏覽器名稱是 "flex",部分是 "flex-grow",因此我們可以用昨天剛學到的 .includes('flex') 處理
function toggleActive(e){
  console.log(e.propertyName);
  if(e.propertyName.includes('flex')){
    this.classList.toggle('open-active');
  }
}
panels.forEach(panel => {
  panel.addEventListener('transitionend', toggleActive);
})
.panels {
  min-height: 100vh;
  overflow: hidden;
  display: flex;
}
.panel {
  display: flex;
  flex-direction: column;
  justify-content: center;
  flex: 1;
/*   省略... */
}
.panel > * {
/*margin: 0;
  width: 100%;
  transition: transform 0.5s; */
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}
.panel > *:first-child{ transform: translateY(-100%); }
.panel.open-active > *:first-child{transform: translateY(0);}
.panel > *:last-child{ transform: translateY(100%); }
.panel.open-active > *:last-child{transform: translateY(0);}
.panel.open {
  flex: 5;
  font-size: 40px;
}
const panels = document.querySelectorAll('.panel');
function toggleOpen(){
  console.log(this);
  this.classList.toggle('open');
}
function toggleActive(e){
  console.log(e);
  if(e.propertyName.includes('flex')){
    this.classList.toggle('open-active');
  }
}
panels.forEach(panel => {
  panel.addEventListener('click', toggleOpen);
});
panels.forEach(panel => {
  panel.addEventListener('transitionend', toggleActive);
})
以上是第五天的製作紀錄,如有錯誤或不足的地方還請多多指教 >.<
Flexbox + JavaScript Image Gallery — #JavaScript30 5/30
[ Alex 宅幹嘛 ] 深入淺出 Javascript30 快速導覽:Day 5:Flex Panel Gallery
MDN Web Docs